/*MyPhotoIndex Free Photo Organizer <www.myphotoindex.com>
  Copyright (C) <2006-2009>  <Asaf Yarkoni asaf@yarkoni.net>

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
using System;
using System.Collections.Generic;
using System.Text;
using MyPhotoIndex.ImageBank;
using MyPhotoIndex.Interfaces;
using MyPhotoIndex.ImageBank.Query;
using MyPhotoIndex.Interfaces.Tagging;
using MyPhotoIndex.Interfaces.Imaging;
using MyPhotoIndex.Interfaces.Queries;

namespace MyPhotoIndex.ImageBank
{
    public class SavedQuery : ISavedQuery
    {
        private Dictionary<int, IImageTag> m_tagMap = new Dictionary<int, IImageTag>();

        private int m_id;

        public int Id
        {
            get {  return m_id;  }
            set { m_id = value; }
        }

        private String m_name;

        public String Name
        {
            get { return m_name; }
            set { m_name = value; }
        }
        private bool m_relation;

        public bool Relation
        {
            get { return m_relation; }
            set { m_relation = value; }
        }
        private int[] m_withAnd;

        public int[] WithAnd
        {
            get { return m_withAnd; }
            set { m_withAnd = value; }
        }
        private int[] m_withOr;

        public int[] WithOr
        {
            get { return m_withOr; }
            set { m_withOr = value; }
        }
        private int[] m_withOut;

        public int[] Without
        {
            get { return m_withOut; }
            set { m_withOut = value; }
        }


        public List<int> ExecuteQuery(bool explicitTagList)
        {
            List<int> distinctList = new List<int>();

            Dictionary<int, IImageData> list = null;
            IImageCollection imageCollection = new QueryHelper(Storage.Instance.UnFiltered);// Storage.Instance;
            List<QueryParameter> queryParams = new List<QueryParameter>();

            foreach (int tag in m_withAnd)
            {
                List<int> tagList = new List<int>();
                if (explicitTagList == false)
                {
                    tagList = ImageTagCollection.Instance.GetTagList(tag);
                }
                else
                {
                    tagList.Add(tag);
                }

                foreach (int tagId in tagList)
                {
                    ImageTagQueryParameter param = new ImageTagQueryParameter(tagId);
                    param.Operation = QueryParameterOperation.Equal;

                    if (tagList.Count > 1 &&
                        tagId != tagList[tagList.Count - 1])
                    {

                        param.Relation = QueryParameterRelation.Or;
                    }
                    else
                    {
                        param.Relation = QueryParameterRelation.And;
                    }

                    queryParams.Add(param);
                }

                distinctList.AddRange(tagList);
            }

            QueryBuilder qb = null;
            if (m_relation == true &&
                m_withAnd.Length > 0)
            {
                qb = new QueryBuilder(queryParams.ToArray(), imageCollection, true);
                list = qb.RunQuery();
                queryParams.Clear();
                imageCollection = new QueryHelper(list);
            }

            foreach (int tag in m_withOr)
            {
                List<int> tagList = new List<int>();
                if (explicitTagList == false)
                {
                    tagList = ImageTagCollection.Instance.GetTagList(tag);
                }
                else
                {
                    tagList.Add(tag);
                }
        
                foreach (int tagId in tagList)
                {
                    ImageTagQueryParameter param = new ImageTagQueryParameter(tagId);
                    param.Operation = QueryParameterOperation.Equal;
                    param.Relation = QueryParameterRelation.Or;

                    queryParams.Add(param);
                }

                distinctList.AddRange(tagList);
            }

            if (queryParams.Count > 0)
            {
                qb = new QueryBuilder(queryParams.ToArray(), imageCollection, true);
                list = qb.RunQuery();
                queryParams.Clear();
                imageCollection = new QueryHelper(list);
            }

            foreach (int tag in m_withOut)
            {
                List<int> tagList = new List<int>();
                if (explicitTagList == false)
                {
                    tagList = ImageTagCollection.Instance.GetTagList(tag);
                }
                else
                {
                    tagList.Add(tag);
                }

                List<int> withoutList = new List<int>(m_withOut);
                foreach (int tagId in tagList)
                {
                    if (distinctList.Contains(tagId) == false ||
                        withoutList.Contains(tagId) == true)
                    {
                        ImageTagQueryParameter param = new ImageTagQueryParameter(tagId);
                        param.Operation = QueryParameterOperation.NotEqual;
                        param.Relation = QueryParameterRelation.And;

                        queryParams.Add(param);
                    }
                }

                distinctList.AddRange(tagList);
            }

            if (queryParams.Count > 0)
            {
                qb = new QueryBuilder(queryParams.ToArray(), imageCollection, true);
                list = qb.RunQuery();
            }

            List<int> filteredList = new List<int>();
            foreach (int imageId in list.Keys)
            {
                filteredList.Add(imageId);
            }

            return filteredList;
        }
    }
}
